package com.poseidon.prototype;

import java.io.IOException;
import java.net.URL;

import com.jme.bounding.OrientedBoundingBox;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jmex.model.collada.ColladaImporter;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.Joint;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.material.Material;


public class Robot extends Node{

	private static final long serialVersionUID = 1L;

	private static final Vector3f ENGINE1 = new Vector3f( 1, 0, 1 );
	private static final Vector3f ENGINE2= new Vector3f( -1,0, 1 );
	private static final Vector3f ENGINE3 = new Vector3f( 1, 0, -1 );
	private static final Vector3f ENGINE4 = new Vector3f( -1,0, -1 );
	private static final Vector3f ENGINE5 = new Vector3f( 0, 0, 0 );

	private static final int FORWARD=1;
	private static final int BACKWARD=-1;
	private static final int UP=2;
	private static final int DOWN=-2;
	private Physics physics;
	public DynamicPhysicsNode chassisNode,dynamicNodeEngine1,dynamicNodeEngine2,dynamicNodeEngine3,dynamicNodeEngine4,dynamicNodeEngine5;

	private Engine engine1, engine2, engine3, engine4, engine5;

	public Robot(final PhysicsSpace pSpace, Physics physics ){
		super("Robot");
		this.physics=physics;
		createRobot("Falcon","jmetest/data/model/falconTest.dae",pSpace);
		createEngineBases(pSpace);
		createEngine(pSpace);

	}

	private void createRobot(String name, String pathToFile, final PhysicsSpace pSpace){
		chassisNode = pSpace.createDynamicNode();
		chassisNode.setName(name);
		chassisNode.setMass(100);
		createObject(chassisNode,name,pathToFile,pSpace);
	}

	/*
	 *	Arvanitidis Georgios	2009/11/25
	 *	createObject(DynamicPhysicsNode object,String name, String pathToFile, final PhysicsSpace pSpace);
	 *	this method loads the COLLADA model from the input directory.
	 *	The COLLADA fire provide various information, like the 3D graphics.
	 */
	@SuppressWarnings("static-access")
	private void createObject(DynamicPhysicsNode object,String name, String pathToFile, final PhysicsSpace pSpace){

		URL model = Robot.class.getClassLoader().getResource(pathToFile);

        try {
        	ColladaImporter.load(model.openStream(), name);
        	Node myModel = (Node) ColladaImporter.getModel();
    		ColladaImporter.cleanUp();
	    	myModel.setModelBound(new OrientedBoundingBox());
	    	myModel.updateModelBound();

	        //Attach the file model to the dynamic node
	    	object.setName(name);
	    	object.attachChild(myModel);
	    	Quaternion q = new Quaternion();
	    	q.fromAngleAxis(FastMath.PI/2, new Vector3f(-1,0,0));
	    	object.setLocalRotation(q);
	    	object.setLocalScale(.08f);

	        //Generete the physics
	    	object.generatePhysicsGeometry(myModel,object,false);
    	} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(0);
		}
    	this.attachChild(object);
	}

	/**
	 * Samuele Sabbatini
     *
     *
     *
     * @param pSpace physics Space
     * @return
     */

	 private void createEngineBases( final PhysicsSpace pSpace ) {
	    	dynamicNodeEngine1 = createBase( pSpace,ENGINE1);
	        createEngineJoint( pSpace, dynamicNodeEngine1 );
	        dynamicNodeEngine2 = createBase( pSpace,ENGINE2 ) ;
	        createEngineJoint( pSpace, dynamicNodeEngine2 );
	    	dynamicNodeEngine3 = createBase( pSpace,ENGINE3 );
	    	createEngineJoint( pSpace, dynamicNodeEngine3 );
	        dynamicNodeEngine4 = createBase( pSpace, ENGINE4);
	        createEngineJoint( pSpace, dynamicNodeEngine4 );
	    	dynamicNodeEngine5 = createBase( pSpace, ENGINE5);
	    	createEngineJoint( pSpace, dynamicNodeEngine5 );
	    }

	    private DynamicPhysicsNode createBase( final PhysicsSpace pSpace, final Vector3f relativePosition ) {
	        DynamicPhysicsNode engineBase = pSpace.createDynamicNode();
	        engineBase.setName( "EngineBase" );
	        engineBase.setLocalTranslation( relativePosition);
	        engineBase.createBox( "baseBox" );
	        engineBase.setLocalScale( 0.1f );
	        engineBase.setMass( 1 );
	        engineBase.setMaterial( Material.GHOST );
	        this.attachChild( engineBase );
	        return engineBase;
	    }

	    private Joint createEngineJoint( final PhysicsSpace pSpace, DynamicPhysicsNode dynamicNodeEngine ) {
	        Joint engineJoint = pSpace.createJoint();
	        engineJoint.attach( dynamicNodeEngine, chassisNode );

	        return engineJoint;
	    }

	private void createEngine(final PhysicsSpace pSpace){
			engine1 = new Engine(dynamicNodeEngine1,ENGINE1,1,pSpace,physics);
	        this.attachChild( engine1);
	        engine2 = new Engine(dynamicNodeEngine2,ENGINE2,-1,pSpace,physics);
	        this.attachChild( engine2 );
		   	engine3 = new Engine(dynamicNodeEngine3,ENGINE3,-1,pSpace,physics);
	        this.attachChild( engine3);
	        engine4 = new Engine(dynamicNodeEngine4,ENGINE4,1,pSpace,physics);
	        this.attachChild( engine4 );
	        engine5 = new Engine(dynamicNodeEngine5,ENGINE5,0,pSpace,physics);
	        this.attachChild( engine5 );
	}



    public DynamicPhysicsNode getChassis() {
		return chassisNode;
	}

    /*
     *	Arvanitidis Georgios	2009/12/2
     *	enableEngine(int direction)
     *	this method implements the moving of the robot.
     *	Added the up/down movement!
     *	Up/Down/Forward -> perfect
     *	Right/Left -> no perfect
     *	int direction -> this parametes provide the infromation of the direction
     */
    public void enableEngine(int direction){

    	Vector3f positionChassis=chassisNode.getLocalTranslation();

    	Vector3f positionEngine1=engine1.getCenter();
    	Vector3f distanceEngine1= directionForce(positionEngine1,positionChassis);

     	Vector3f positionEngine2=engine2.getCenter();
    	Vector3f distanceEngine2= directionForce(positionEngine2,positionChassis);

    	Vector3f positionEngine5=engine5.getCenter();
    	Vector3f distanceEngine5= directionForce(positionEngine2,positionChassis);


    	if (direction==0){

    		engine1.activation(FORWARD,distanceEngine1,physics.getRobotThrustForwardForce());
    		engine2.activation(FORWARD,distanceEngine2,physics.getRobotThrustForwardForce());
    		engine3.activation(FORWARD,distanceEngine2,physics.getRobotThrustForwardForce());
    		engine4.activation(FORWARD,distanceEngine1,physics.getRobotThrustForwardForce());
    	}
    	if (direction==1){
    		engine5.activation(UP,distanceEngine5,physics.getRobotThrustVerticalForce());
    	}
    	if (direction==2){
    		engine5.activation(DOWN,distanceEngine5,physics.getRobotThrustVerticalForce());
    	}
    	if (direction==3){
    		engine1.activation(FORWARD,distanceEngine1,physics.getRobotThrustLateralForce());
        	engine2.activation(BACKWARD,distanceEngine2,physics.getRobotThrustLateralForce());
        	engine3.activation(FORWARD,distanceEngine2,physics.getRobotThrustLateralForce());
        	engine4.activation(BACKWARD,distanceEngine1,physics.getRobotThrustLateralForce());}
    	if (direction==4){
    		engine1.activation(BACKWARD,distanceEngine1,physics.getRobotThrustLateralForce());
        	engine2.activation(FORWARD,distanceEngine2,physics.getRobotThrustLateralForce());
        	engine3.activation(BACKWARD,distanceEngine2,physics.getRobotThrustLateralForce());
        	engine4.activation(FORWARD,distanceEngine1,physics.getRobotThrustLateralForce());
        }
    //	System.out.println (distanceEngine);
    }


    private Vector3f directionForce(Vector3f positionEngine, Vector3f positionChassis){

    	Vector3f distance= new Vector3f((positionEngine.x-positionChassis.x),(positionEngine.y-positionChassis.y),(positionEngine.z-positionChassis.z));

    	return distance;
    }
	/*
	 *	Arvanitidis Georgios	2009/12/9
	 *	disableEngine(int direction)
	 *	this method implements this behavior, as long as you pressing the key
	 *	the robot keeps on moving, based on the button that you pressed.
	 *	When you leave the button the robot stops.
	 *	Up/Down/Forward -> perfect
	 *	Right/Left -> no perfect
	 *	int direction -> this parametes provide the infromation of the direction
	 *	that the robot moved before.
	 */

    public void physicsForces(){

    engine1.physicsForces();
    engine2.physicsForces();
    engine3.physicsForces();
    engine4.physicsForces();
    engine5.physicsForces();
    };


	public void disableEngine(int direction){

	    }

}